/*********************************************************************************************************
 *  ------------------------------------------------------------------------------------------------------
 *  file description
 *  ------------------------------------------------------------------------------------------------------
 *         \file  cant.h
 *         \unit  cant
 *        \brief  This is a can test for C language
 *       \author  Lamdonn
 *      \version  v0.1.0
 *      \license  GPL-2.0
 *    \copyright  Copyright (C) 2023 Lamdonn.
 ********************************************************************************************************/
#ifndef __cant_H
#define __cant_H

#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>

/* Version infomation */
#define CANT_V_MAJOR                        0
#define CANT_V_MINOR                        1
#define CANT_V_PATCH                        0

#define CANT_BAUDRATE_125K                  0
#define CANT_BAUDRATE_250K                  1
#define CANT_BAUDRATE_500K                  2
#define CANT_BAUDRATE_800K                  3
#define CANT_BAUDRATE_1000K                 4
#define CANT_BAUDRATE_MAX                   5

#define CANT_E_OK                           0  // Success
#define CANT_E_INVALID                      1  // Invalid `cant` pointer
#define CANT_E_DATA                         2  // Invalid `data` pointer
#define CANT_E_LEN                          3  // Invalid legth
#define CANT_E_NTEST                        4  // CANT load testing has not started
#define CANT_E_OVER                         5  // CANT load exceeds range
#define CANT_E_LINK                         6  // Invalid `link` pointer
#define CANT_E_RATE                         7  // Invalid `rate` pointer
#define CANT_E_TRANSMIT                     8  // Invalid `transmit` pointer
#define CANT_E_TRANSFAIL                    9  // Invalid `transmit` pointer
#define CANT_E_LOAD                         10  // Invalid `load` pointer
#define CANT_E_DCANID                       11  // Dummy canids that do not match
#define CANT_E_ECANID                       12  // Error canid

// Function pointer type for functions related to CAN transfer.
// It takes a CAN ID (uint32_t), a pointer to data (uint8_t), and the length of the data (uint16_t) as parameters
// and returns an int. It can be used for functions like CAN transmission or reception.
typedef int (*cant_transfer_t)(uint32_t canid, uint8_t *data, uint16_t length);

// Structure definition for the CANT (presumably related to CAN bus) structure.
typedef struct 
{
    // Inner structure for configuration related to the CAN functionality.
    struct 
    {
        // Channel number of the CAN bus, represented as a uint8_t.
        uint8_t channel;
        // Baud rate of the CAN bus, represented as a uint8_t.
        uint8_t baundrate;
        // Call period for the 'cant_task()' function, represented as a uint16_t.
        uint16_t period;                        // `cant_task()` call period
        // Function pointer for CAN transmission. It points to a function that can transmit data on the CAN bus.
        cant_transfer_t transmit;               // can transmit the drive function
        // Function pointer for CAN reception. It points to a function that can handle received data on the CAN bus.
        cant_transfer_t receive;                // can receive hook functions
    } config;
    
    // Bus load value of the CAN bus, represented as a uint16_t.
    uint16_t busload;
    // Value related to period bits (specific meaning depends on the context), represented as a uint32_t.
    uint32_t periodbits;
    // Timestamp value, represented as a uint32_t.
    uint32_t timestamp;

    // Inner structure for dummy data related to CAN operations.
    struct 
    {
        // CAN ID, represented as a uint32_t.
        uint32_t canid;
        // Compression factor, represented as a float.
        float compression;
        // Rate value, represented as a float.
        float rate;
        // Target load value, represented as a uint16_t.
        uint16_t tarload;
        // Base value for the gap (specific meaning depends on the context), represented as a uint32_t.
        uint32_t gapbase;
        // Count value for the gap (specific meaning depends on the context), represented as a uint32_t.
        uint32_t gapcount;
        // Current count value, represented as a uint32_t.
        uint32_t curcount;
        // Array to store data, with a size of 64 bytes.
        uint8_t data[64];
    } dummy;

    // Inner structure for verification related data in CAN operations.
    struct 
    {
        // CAN ID, represented as a uint32_t.
        uint32_t canid;
        // Error count value, represented as a uint32_t.
        uint32_t errcount;
        // Current count value, represented as a uint32_t.
        uint32_t curcount;
        // Verification count value, represented as a uint32_t.
        uint32_t vercount;
        // Last count value, represented as a uint32_t.
        uint32_t lstcount;
    } verify;
} CANT;

/**
 * \brief Sets the CAN ID for the CAN device's dummy data.
 * \param cant: Pointer to the CANT structure representing the CAN device.
 * \param canid: The CAN ID value to be set.
 * \return CANT_E_OK if the setting is successful, CANT_E_INVALID if the pointer is NULL,
 *         CANT_E_ECANID if the provided CAN ID is 0.
 * 
 * This function checks if the provided pointer is valid. 
 */
int cant_set_dummy_canid(CANT *cant, uint32_t canid);

/**
 * \brief Sets the CAN ID for the verification settings in the CAN device.
 * \param cant: Pointer to the CANT structure representing the CAN device.
 * \param canid: The CAN ID value to be set.
 * \return CANT_E_OK if the setting is successful, CANT_E_INVALID if the pointer is NULL,
 *         CANT_E_ECANID if the provided CAN ID is 0.
 * 
 * This function checks if the provided pointer is valid. 
 */
int cant_set_verify_canid(CANT *cant, uint32_t canid);

/**
 * \brief Sets the target bus load for the CAN device's dummy data.
 * \param cant: Pointer to the CANT structure representing the CAN device.
 * \param load: The target bus load value to be set.
 * \return CANT_E_OK if the setting is successful, CANT_E_INVALID if the pointer is NULL.
 * 
 * This function checks if the provided pointer is valid. 
 */
int cant_set_busload(CANT *cant, uint16_t load);

/**
 * \brief Retrieves the target bus load for the CAN device's dummy data.
 * \param cant: Pointer to the CANT structure representing the CAN device.
 * \param load: Pointer to a variable where the target bus load will be stored.
 * \return CANT_E_OK if the retrieval is successful, CANT_E_INVALID if the pointer is NULL,
 *         CANT_E_LOAD if the provided load pointer is NULL.
 * 
 * This function checks if the provided pointers are valid. 
 */
int cant_get_busload(CANT *cant, uint16_t *load);

/**
 * \brief Transmits data over the CAN bus using the provided CAN device configuration.
 * \param cant: Pointer to the CANT structure representing the CAN device.
 * \param canid: The CAN ID to which the data will be transmitted.
 * \param data: Pointer to the data buffer to be transmitted.
 * \param length: The length of the data buffer.
 * \return CANT_E_OK if the transmission is successful, appropriate error codes otherwise.
 *         CANT_E_INVALID if the pointer to the CANT structure is NULL.
 *         CANT_E_DATA if the data pointer is NULL.
 *         CANT_E_TRANSMIT if the transmission function pointer in the configuration is NULL.
 *         CANT_E_TRANSFAIL if the actual transmission function returns a non-zero value.
 * 
 * This function first checks the validity of the input parameters. 
 */
int cant_transmit(CANT *cant, uint32_t canid, uint8_t *data, uint16_t length);

/**
 * \brief Receives data over the CAN bus and performs related operations.
 * \param cant: Pointer to the CANT structure representing the CAN device.
 * \param canid: The CAN ID from which the data is received.
 * \param data: Pointer to the buffer where the received data will be stored.
 * \param length: The length of the received data.
 * \return CANT_E_OK if the operation is successful, CANT_E_INVALID if the pointer to the CANT structure is NULL.
 * 
 * This function first checks the validity of the input pointer. 
 */
int cant_receive(CANT *cant, uint32_t canid, uint8_t *data, uint16_t length);

/**
 * \brief Initializes the CANT structure representing the CAN device.
 * \param cant: Pointer to the CANT structure to be initialized.
 * \return CANT_E_OK if the initialization is successful, CANT_E_INVALID if the pointer is NULL.
 * 
 * This function initializes various fields in the CANT structure. 
 */
int cant_init(CANT *cant);

/**
 * \brief The main task function for the CAN device.
 * \param cant: Pointer to the CANT structure representing the CAN device.
 * \return CANT_E_OK if the task is executed successfully, CANT_E_INVALID if the pointer is NULL.
 * 
 * This function is the main task handler for the CAN device. It updates the timestamp of the
 * CAN device. Based on the timestamp value, it performs different operations at specific intervals.
 */
int cant_task(CANT *cant);

#endif
